<script setup lang="ts">
import { ref, nextTick, defineEmits, onMounted, onUnmounted, watch, computed, reactive } from 'vue'
import { NIcon, NScrollbar } from 'naive-ui'
import { Share24Regular } from '@vicons/fluent'
// 勾选
import MessageGroup from '@/views/LLMStudio2/ChatModelPanel/ChatInterface/MessageGroup.vue'
import type { TextMessage, MessageGroupList } from './type'
import LexicalEditor from '@/views/LLMStudio2/ChatModelPanel/ChatInterface/prompt-editor/index.vue'
import { FileText, Refresh, Trash } from '@vicons/tabler'
import ShareModal from '@/views/LLMStudio2/ChatModelPanel/ChatInterface/ShareModal.vue'
import ChatInterfaceHeader from '@/views/LLMStudio2/ChatModelPanel/ChatInterface/ChatInterfaceHeader.vue'
import { getAppById } from '@/service/api/userApp'
import type { AppItem } from '@/types/userApp'
import PageLoading from '@/views/LLMStudio2/ChatModelPanel/ChatInterface/PageLoading.vue'
import RightPanel from '@/views/LLMStudio2/ChatModelPanel/AppRightPanel/index.vue'

const state = reactive({
  messages: [] as MessageGroupList,
  inputMessage: '',
  isReplying: false,
  inputHeight: 100,
  isSendingDisabled: false,
  isAtBottom: true,
  isShared: false,
  sharedGroups: [] as number[],
  showShareModal: false,
  shareUrl: 'https://example.com/share/123',
  isNetSearch: false,
  currentAppId: null as number | null,
  currentApp: {} as Partial<AppItem>,
  showPageLoading: true
})

const previewMessage = computed(
  (): TextMessage => ({
    id: -1,
    content: state.inputMessage,
    sender: 'user',
    timestamp: Date.now(),
    type: 'text'
  })
)

const handleDeleteMessage = (groupId: number) => {
  const groupIndex = state.messages.findIndex((group) => group.id === groupId)
  if (groupIndex !== -1) {
    state.messages.splice(groupIndex, 1)
  }
}

const stopReplying = () => {
  const loadingIndex = state.messages.findIndex((group) =>
    group.messageList.some((m) => 'isLoading' in m && m.isLoading)
  )
  if (loadingIndex !== -1) {
    state.messages[loadingIndex].messageList = state.messages[loadingIndex].messageList.filter(
      (m) => !('isLoading' in m) || !m.isLoading
    )
    state.isReplying = false
    state.isSendingDisabled = false
  }
}

const scrollToBottom = () => {
  nextTick(() => {
    if (messageBodyRef.value && state.isAtBottom) {
      setTimeout(() => {
        messageBodyRef.value?.scrollTo({
          top: messageBodyRef.value.scrollHeight,
          behavior: 'smooth'
        })
      }, 150)
    }
  })
}

const updateInputHeight = () => {
  const inputElement = document.querySelector('.inputs') as HTMLElement
  if (inputElement) {
    state.inputHeight = inputElement.offsetHeight
  }
  scrollToBottom()
}

onMounted(() => {
  window.addEventListener('resize', updateInputHeight)
  setTimeout(updateInputHeight, 100)
})

onUnmounted(() => {
  window.removeEventListener('resize', updateInputHeight)
})

watch(state.inputMessage, () => {
  nextTick(updateInputHeight)
})

const onScrollHandler = (event: Event) => {
  const target = event.target as HTMLElement
  if (target && target.scrollHeight - target.scrollTop === target.clientHeight) {
    state.isAtBottom = true
  } else {
    state.isAtBottom = false
  }
}

const handleShowLog = (messageId: number) => {
  // Implement logic to show log
  console.log('Show log for message:', messageId)
}

const handleRegenerateMessage = (messageId: number) => {
  // Implement logic to regenerate answer
  console.log('Regenerate answer for message:', messageId)
}

const toggleShare = (groupId: number) => {
  state.isShared = true

  const index = state.sharedGroups.indexOf(groupId)
  if (index === -1) {
    state.sharedGroups.push(groupId)
  } else {
    state.sharedGroups.splice(index, 1)
  }
}

const showShareDialog = () => {
  state.showShareModal = true
}
const handleConfirm = () => {
  state.showShareModal = false
  state.isShared = false
}

const handleSend = (message: string) => {
  console.log('handleSend', message)
}

const changeApp = async (appId: number) => {
  state.showPageLoading = true
  state.currentAppId = appId
  try {
    const res = await getAppById(appId)
    await new Promise((resolve) => setTimeout(resolve, 1000)) // 模拟延迟
    state.currentApp = res.data
  } catch (error) {
    console.error('Failed to fetch app:', error)
  } finally {
    state.showPageLoading = false
  }
}

defineExpose({
  changeApp
})

const handleNewChat = () => {
  console.log('handleNewChat')
}

const messageBodyRef = ref<HTMLElement | null>(null)
</script>

<template>
  <div
    class="w-full h-full flex flex-col rounded-2xl bg-[#F9FAFB] relative"
    role="region"
    aria-label="Chat Interface"
  >
    <ChatInterfaceHeader
      v-model:isShared="state.isShared"
      @showShareDialog="showShareDialog"
      :title="state.currentApp.title"
    />
    <NScrollbar
      ref="messageBodyRef"
      :style="{
        maxHeight: `calc(100vh - ${state.inputHeight}px - 103px)`,
        position: 'relative'
      }"
      content-style="padding: 10px"
      @scroll="onScrollHandler"
    >
      <template v-for="({ id, messageList }, index) in state.messages" :key="id">
        <MessageGroup
          :id="id"
          :message-list="messageList"
          :is-replying="state.isReplying && index === state.messages.length - 1"
          :is-analysis-mode="false"
          :is-shared="state.isShared"
          :is-selected="state.sharedGroups.includes(id)"
          @delete="handleDeleteMessage"
          @show-log="handleShowLog"
          @regenerate="handleRegenerateMessage"
          @toggle-share="toggleShare"
        >
          <template #toolbar>
            <div
              v-if="!state.isShared"
              @click="toggleShare(id)"
              class="cursor-pointer text-gray-500 text-11px px-1 py-0.5 rounded-lg hover:bg-gray-200 flex items-center justify-center gap-2"
            >
              <NIcon :size="15" :component="Share24Regular" /> 分享
            </div>
            <div
              @click="handleShowLog"
              class="cursor-pointer text-gray-500 text-11px px-1 py-0.5 rounded-lg hover:bg-gray-200 flex items-center justify-center gap-2"
            >
              <NIcon :size="15" :component="FileText" /> 执行日志
            </div>
            <div
              @click="handleRegenerate"
              class="cursor-pointer text-gray-500 text-11px px-1 py-0.5 rounded-lg hover:bg-gray-200 flex items-center justify-center gap-2"
            >
              <NIcon :size="15" :component="Refresh" /> 重新回答
            </div>
            <div
              @click="handleDelete"
              class="cursor-pointer text-gray-500 text-11px px-1 py-0.5 rounded-lg hover:bg-gray-200 flex items-center justify-center gap-2 text-red-500"
            >
              <NIcon :size="15" :component="Trash" color="#f03e3e" /> 删除
            </div>
          </template>
        </MessageGroup>
      </template>
      <div v-if="state.inputMessage" class="mb-4">
        <MessageGroup
          :id="0"
          :message-list="[previewMessage]"
          :is-replying="false"
          :is-analysis-mode="false"
          :is-shared="false"
          :is-selected="false"
        />
      </div>
      <div v-if="state.isReplying" class="absolute bottom-1.5" style="left: calc(50% - 100px)">
        <div
          class="text-gray-500 flex items-center text-13px gap-1.5 cursor-pointer animate-breathe border border-solid border-gray-200 px-3.5 py-1 rounded-full hover:bg-gray-200 active:bg-gray-300"
          @click="stopReplying"
        >
          <div class="breathing text-lg h-4 w-4 inline-block mr-1.5 animate-breathe"></div>
          停止回复
        </div>
      </div>
    </NScrollbar>
    <LexicalEditor
      v-model:isNetSearch="state.isNetSearch"
      @send="handleSend"
      v-model:currentModel="state.currentApp.modelId"
      @newChat="handleNewChat"
    ></LexicalEditor>
    <ShareModal
      v-model:show="state.showShareModal"
      :share-url="state.shareUrl"
      @confirm="handleConfirm"
    />
    <PageLoading :show="state.showPageLoading" />
  </div>
  <RightPanel />
</template>

<style scoped lang="scss">
.message_body {
  height: calc(100% - 120px);

  .mb-4:last-child {
    margin-bottom: 2rem;
  }
}

.inputs {
  border: 1px solid rgba(128, 128, 128, 0.1);
  border-right: none;
  width: calc(100% - 20px);
}

.breathing {
  animation: breathing 2s infinite;
}

@keyframes breathing {
  0%,
  100% {
    background-color: rgba(255, 0, 0, 0.4);
  }

  50% {
    background-color: rgba(255, 0, 0);
  }
}
</style>
